package dao;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import beans.HttpConfig;
import beans.SocketLog;
import utils.Log4jInit;

public class SocketLogDao {

    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    //timeLimit：用于控制日志显示的时间长短，只显示前TIME_LIMIT天的日志
    private static String TIME_LIMIT = HttpConfig.timeLimit;

    /**
     * 2018-7-12记录，algorithm_state的值为0，1，2，意义分别是：（4：失败，1：成功，2：运行中，3：暂停，5：终止）
     * @param taskHash
     * @param subTaskHash
     * @param logFileUri
     * @param algorithmState
     * @param algorithmSchedule
     * @param logLevel
     * @param logMessage
     * @return
     */
    public boolean insertLog(String taskHash, String subTaskHash, String logFileUri, String algorithmState,
                             String algorithmSchedule, String logLevel, String logMessage,String jobId){
        String sql = "insert into `socket_log`(task_hash, sub_task_hash, log_file_uri, algorithm_state, algorithm_schedule," +
                "log_level, time, log_message, job_id) values (?,?,?,?,?,?,now(),?,?)";
        Object[] params = new Object[]{taskHash,subTaskHash,logFileUri,algorithmState,algorithmSchedule,logLevel,logMessage,jobId};
        return Query.executeDML(sql, params)>0;
    }

    public boolean insertLogMessage(String logLevel, String logMessage, String taskHash, String subTaskHash){
        if(logNum(taskHash,subTaskHash)>0){
            return updateLogMessage(logMessage,taskHash,subTaskHash);
        }
        else{
           return insertLog(taskHash, subTaskHash,"","","",logLevel,logMessage,"");
        }
    }

    private boolean updateLogMessage(String logMessage, String taskHash, String subTaskHash){
        String sql = "update `socket_log` set log_message = ?, time=now() where task_hash = ? and sub_task_hash = ?";
        Object[] params = new Object[]{logMessage, taskHash, subTaskHash};
        return Query.executeDML(sql, params)>0;
    }


    /**
     * 2018-7-12记录，algorithm_state的值为0，1，2，意义分别是：（4：失败，1：成功，2：运行中，3：暂停，5：终止）
     * @param logLevel
     * @param algorithmState
     * @param taskHash
     * @param subTaskHash
     * @param jobId
     * @return
     */
    public boolean insertAlgorithmState(String logLevel, String algorithmState, String taskHash, String subTaskHash, String jobId){
        boolean result = false;
        if(logNum(taskHash,subTaskHash)>0){
            result = updateAlgorithmState(algorithmState,taskHash,subTaskHash);
        }
        else{
            result = insertLog(taskHash, subTaskHash,"",algorithmState,"",logLevel,"",jobId);
        }
        //算法状态为1的时候即为算法完成时，需要将进度信息更新为100
        if(Integer.parseInt(algorithmState)==1)
        {
            result = result && insertAlgorithmSchedule(logLevel,"100",taskHash,subTaskHash);
        }
        return result;
    }

    private boolean updateAlgorithmState(String algorithmState, String taskHash, String subTaskHash){
        String sql = "update `socket_log` set algorithm_state = ?, time=now() where task_hash = ? and sub_task_hash = ?";
        Object[] params = new Object[]{algorithmState, taskHash, subTaskHash};
        return Query.executeDML(sql, params)>0;
    }

    public boolean insertAlgorithmSchedule(String logLevel, String algorithmSchedule, String taskHash, String subTaskHash){
        if(logNum(taskHash,subTaskHash)>0){
            return updateAlgorithmSchedule(algorithmSchedule,taskHash,subTaskHash);
        }
        else{
            return insertLog(taskHash, subTaskHash,"","",algorithmSchedule,logLevel,"","");
        }
    }

    private boolean updateAlgorithmSchedule(String algorithmSchedule, String taskHash, String subTaskHash){
        String sql = "update `socket_log` set algorithm_schedule = ?, time=now() where task_hash = ? and sub_task_hash = ?";
        Object[] params = new Object[]{algorithmSchedule, taskHash, subTaskHash};
        return Query.executeDML(sql, params)>0;
    }

    public boolean insertLogFileUri(String logLevel, String logFileUri, String taskHash, String subTaskHash){
        if(logNum(taskHash,subTaskHash)>0){
            return updateLogFileUri(logFileUri,taskHash,subTaskHash);
        }
        else{
            return insertLog(taskHash, subTaskHash,logFileUri,"","",logLevel,"","");
        }
    }

    private boolean updateLogFileUri(String logFileUri, String taskHash, String subTaskHash){
        String sql = "update `socket_log` set log_file_uri = ?, time=now() where task_hash = ? and sub_task_hash = ?";
        Object[] params = new Object[]{logFileUri, taskHash, subTaskHash};
        return Query.executeDML(sql, params)>0;
    }

    public int logNum(String taskHash, String subTaskHash){
        String sql = "select count(*) from `socket_log` where task_hash = ? and sub_task_hash = ?";
        Object[] params = new Object[]{taskHash, subTaskHash};
        return PublicDao.oneNum(sql,params);
    }

    public List<Object> logList(Integer onePageCount, Integer currentPage) {
        String sql = "select * from `socket_log` order by time desc limit "
                + (currentPage - 1) * onePageCount + " , " + onePageCount;
        return socketLogDetail(sql,null);
    }

    private List<Object> socketLogDetail(String sql, Object[] params) {
        final List<Object> results = new ArrayList<>();
        return Query.executeQueryList(results, sql,params, new QueryCallBackList() {
            @Override
            public List<Object> doExecuteList(ResultSet rs, List<Object> results) {
                try {
                    while (rs.next()) {
                        SocketLog socketLog = new SocketLog();
                        socketLog.setTaskHash(rs.getString("task_hash"));
                        socketLog.setSubTaskHash(rs.getString("sub_task_hash"));
                        String filePath = rs.getString("log_file_uri");
                        filePath = filePath.substring(filePath.lastIndexOf("/")+1,filePath.length());
                        socketLog.setLogFileUri(filePath);
                        socketLog.setAlgorithmState(convertAlgorithmState(rs.getString("algorithm_state")));
                        socketLog.setAlgorithmSchedule(rs.getString("algorithm_schedule"));
                        socketLog.setLogLevel(convertLogLevel(rs.getString("log_level")));
                        socketLog.setTime(simpleDateFormat.format(simpleDateFormat.parse(rs.getString("time"))));
                        socketLog.setLogMessage(rs.getString("log_message"));
                        results.add(socketLog);
                    }
                } catch (SQLException | ParseException e) {
                    e.printStackTrace();
                }
                return results;
            }
        });
    }

    private String convertAlgorithmState(String algorithmState){
        String result = null;
        switch (algorithmState){
            case "1":
                result =  "成功";
                break;
            case "2":
                result =  "运行中";
                break;
            case "4":
                result =  "失败";
                break;
            case "3":
                result =  "暂停";
                break;
            case "5":
                result =  "终止";
                break;
            default:
                result = algorithmState;
        }
        return result;
    }

    private String reConvertAlgorithmState(String algorithmState){
        if("成功".contains(algorithmState))
            return "1";
        if("运行中".contains(algorithmState))
            return "2";
        if("失败".contains(algorithmState))
            return "4";
        if("暂停".contains(algorithmState))
            return "3";
        if("终止".contains(algorithmState))
            return "5";
        else
            return algorithmState;
    }

    private String convertLogLevel(String logLevel){
        String result = null;
        switch (logLevel){
            case "1":
                result =  "debug";
                break;
            case "2":
                result =  "info";
                break;
            case "3":
                result =  "warning";
                break;
            case "4":
                result =  "error";
                break;
            default:
                result = logLevel;
        }
        return result;
    }

    /**
     * 将history_job表里面的isSuccess字段转化为socket_log表里面的algorithm_state字段
     * 前者："DONE"  "EXIT" "PAUSE" "RUNNING" "STOP"
     * 后者：4：失败，1：成功，2：运行中，3：暂停，5：终止
     * @param jobStatus
     * @return
     */
    public String historyConvert2Log(String jobStatus){
        String result = null;
        switch (jobStatus){
            case "DONE":
                result =  "1";
                break;
            case "EXIT":
                result =  "4";
                break;
            case "PAUSE":
                result =  "3";
                break;
            case "RUNNING":
                result =  "2";
                break;
            case "STOP":
                result =  "5";
                break;
            default:
                result = jobStatus;
        }
        return result;
    }

    private String reConvertLogLevel(String logLevel){
        logLevel = logLevel.toLowerCase();
        if("debug".contains(logLevel))
            return "1";
        if("info".contains(logLevel))
            return "2";
        if("warning".contains(logLevel))
            return "3";
        if("error".contains(logLevel))
            return "4";
        else
            return logLevel;
    }

    public int getLogPageNum(Integer onePageCount) {
        int socketLogNum = this.socketLogNum();
        return (socketLogNum % onePageCount) == 0 ? (socketLogNum / onePageCount) : (socketLogNum / onePageCount + 1);
    }

    private int socketLogNum() {
        String sql = "select count(*) from socket_log";
        return PublicDao.oneNum(sql,null);
    }

    public static void main(String[] args) {
        SocketLogDao socketLogDao = new SocketLogDao();
        boolean a;
        try {
            InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(new File("E:/test.txt")),"gbk");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            StringBuffer result = new StringBuffer();
            String temp = "";
            while((temp=bufferedReader.readLine())!=null){
                String aaa = new String(temp.getBytes(),"utf-8");
                result.append(aaa);
            }
            Log4jInit.logger.info(result.toString());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
//        a = socketLogDao.insertAlgorithmSchedule("logLevel test","schedule test","121","1");
//        a = socketLogDao.insertAlgorithmState("logLevel test","100","121","1");
//        a = socketLogDao.insertLogMessage("logLevel test","end","121","1");
//        a = socketLogDao.insertLog("121","2","e:/232/sdf.txt",
//                "1","1","1","start");
//        a = socketLogDao.insertLogFileUri("22","F:/","121","2");
//        int b = socketLogDao.logNum("121","2");
//        int c = socketLogDao.getLogPageNum(3);
//        List<Object> d = socketLogDao.logList(2,1);
//        System.out.println();
    }

    public String queryAlgorithmStateByJobId(String jobId) {
        String sql = "select algorithm_state from socket_log where job_id = ?";
        Object[] params = {jobId};
        return (String) Query.executeQueryObject(sql, params, new QueryCallBack() {
            @Override
            public Object doExecute(ResultSet rs){
                String result = "";
                try {
                    while(rs.next()){
                        result =  rs.getString("algorithm_state");
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                return result;
            }
        });
    }
    
    public String queryAlgorithmStateBySubTaskHash(String subtaskhash) {
        String sql = "select algorithm_state from socket_log where job_id = ?";
        Object[] params = {subtaskhash};
        return (String) Query.executeQueryObject(sql, params, new QueryCallBack() {
            @Override
            public Object doExecute(ResultSet rs){
                String result = "";
                try {
                    while(rs.next()){
                        result =  rs.getString("algorithm_state");
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                return result;
            }
        });
    }

    /**
     * 2018-7-12记录，algorithm_state的值为0，1，2，意义分别是：（4：失败，1：成功，2：运行中，3：暂停，5：终止）
     * @param algorithmState
     * @param jobId
     * @return
     */
    public boolean updateAlgorithmStateByJobId(String algorithmState, String jobId) {
        String sql = "";
        Object[] params = new Object[]{algorithmState, jobId};
        if(algorithmState.equals("4")||algorithmState.equals("1")||algorithmState.equals("5"))
        {
            sql = "update `socket_log` set algorithm_state = ?, time=now() where job_id = ?";
        }
        else{
            sql = "update `socket_log` set algorithm_state = ?  where job_id = ?";
        }
        boolean result =  Query.executeDML(sql, params)>0;
        if(Integer.parseInt(algorithmState)==1)
        {
            result = result && updateAlgorithmScheduleByJobId("100",jobId);
        }
        return result;
    }

    /**
     * 更新算法的进度信息
     * @param algorithmSchedule
     * @param jobId
     * @return
     */
    public boolean updateAlgorithmScheduleByJobId(String algorithmSchedule, String jobId) {
        String sql = "update `socket_log` set algorithm_schedule = ?, time=now() where job_id = ?";
        Object[] params = new Object[]{algorithmSchedule, jobId};
        return Query.executeDML(sql, params)>0;
    }

    public boolean updateLogFileByJobId(String filePath, String jobId) {
        String sql = "update `socket_log` set log_file_uri = ?, time=now() where job_id = ?";
        Object[] params = new Object[]{filePath, jobId};
        return Query.executeDML(sql, params)>0;
    }

    /**
     * 计算系统任务运行日志的全文搜索
     * @param onePageCount
     * @param currentPage
     * @param match
     * @param startTime
     * @param endTime
     * @return
     */
    public List<Object> logFulltextSearch(Integer onePageCount, Integer currentPage, String match, String startTime, String endTime){
        String startTimeString = startTime==null?"":" and time >= ? ";
        String endTimeString = endTime==null?"":" and time <= ? ";
        String matchString = match==null?"":" and (task_hash REGEXP ?  or sub_task_hash REGEXP ? " +
                "or log_file_uri REGEXP ? or algorithm_state REGEXP ? or algorithm_schedule REGEXP ? " +
                "or log_level REGEXP ? or log_message REGEXP ?) " ;
        Object[] params = null;
        String sql = "select * from socket_log  where TO_DAYS(now()) - TO_DAYS(time) <= "+ TIME_LIMIT + matchString
                + startTimeString + endTimeString + "order by time desc limit "
                + (currentPage - 1) * onePageCount + " , " + onePageCount;
        List<Object> paramsList = new ArrayList<>();
        if(match!=null)
            paramsList.addAll(Arrays.asList(match, match, match, reConvertAlgorithmState(match), match, reConvertLogLevel(match), match));
        if(startTime!=null)
            paramsList.add(startTime);
        if(endTime!=null)
            paramsList.add(endTime);
        if(paramsList.size()>0)
        {
            params = new Object[paramsList.size()];
            for(int i=0;i<paramsList.size();i++)
            {
                params[i] = paramsList.get(i);
            }
        }
        return socketLogDetail(sql,params);
    }

    /**
     * 计算系统任务运行日志搜索结果页数计算
     * @param onePageCount
     * @param currentPage
     * @param match
     * @param startTime
     * @param endTime
     * @return
     */
    public int logFulltextSearchNum(Integer onePageCount, Integer currentPage, String match, String startTime, String endTime){
        String startTimeString = startTime==null?"":" and time >= ? ";
        String endTimeString = endTime==null?"":" and time <= ? ";
        String matchString = match==null?"":" and (task_hash REGEXP ?  or sub_task_hash REGEXP ? " +
                "or log_file_uri REGEXP ? or algorithm_state REGEXP ? or algorithm_schedule REGEXP ? " +
                "or log_level REGEXP ? or log_message REGEXP ?) " ;
        Object[] params = null;
        String sql = "select count(*) from socket_log where TO_DAYS(now()) - TO_DAYS(time) <= "+ TIME_LIMIT + matchString
                + startTimeString + endTimeString;
        List<Object> paramsList = new ArrayList<>();
        if(match!=null)
            paramsList.addAll(Arrays.asList(match, match, match, match, match, match, match));
        if(startTime!=null)
            paramsList.add(startTime);
        if(endTime!=null)
            paramsList.add(endTime);
        if(paramsList.size()>0)
        {
            params = new Object[paramsList.size()];
            for(int i=0;i<paramsList.size();i++)
            {
                params[i] = paramsList.get(i);
            }
        }
        int modelNum = PublicDao.oneNum(sql,params);
        return (modelNum % onePageCount) == 0 ? (modelNum / onePageCount) : (modelNum / onePageCount + 1);
    }
    /** 2019-02-15
     * 将socket_log表里面的algorithm_state字段转化为history_job表里面的isSuccess字段
     * 前者：1：成功，2：运行中，3：暂停，4：失败，5：终止
     * 后者："DONE" "RUNNING" "PAUSE" "EXIT" "STOP"
     * @param jobStatus
     * @return
     */
    public String logConvert2History(String jobStatus){
        String result = null;
        switch (jobStatus){
            case "1":
                result =  "DONE";
                break;
            case "2":
                result =  "RUNNING";
                break;
            case "3":
                result =  "PAUSE";
                break;
            case "4":
                result =  "EXIT";
                break;
            case "5":
                result =  "STOP";
                break;
            default:
                result = jobStatus;
        }
        return result;
    }
    /**
     * 2019-02-15, 通过作业id查询算法日志URI
     * @param jobId  作业id
     * @return
     */
    public String getLogFileUriByJobId(String jobId) {
        String sql = "select log_file_uri from `socket_log` where job_id = ?";
        Object[] params = {jobId};
        return (String) Query.executeQueryObject(sql, params, new QueryCallBack() {
            @Override
            public Object doExecute(ResultSet rs){
                String result = null;
                try {
                    while(rs.next()){
                        result =  rs.getString("log_file_uri");
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                return result;
            }
        });
    }
    
    public String getLogFileUriBySubTaskHash(String subtaskhash) {
        String sql = "select log_file_uri from `socket_log` where task_hash = ?";
        Object[] params = {subtaskhash};
        return (String) Query.executeQueryObject(sql, params, new QueryCallBack() {
            @Override
            public Object doExecute(ResultSet rs){
                String result = null;
                try {
                    while(rs.next()){
                        result =  rs.getString("log_file_uri");
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                return result;
            }
        });
    }

    /**
     * 2019-02-15, 通过作业id查询算法进度
     * @param jobId  作业id
     * @return
     */
    public String getAlgorithmProcessByJobId(String jobId) {
        String sql = "select algorithm_schedule from `socket_log` where job_id = ?";
        Object[] params = {jobId};
        return (String) Query.executeQueryObject(sql, params, new QueryCallBack() {
            @Override
            public Object doExecute(ResultSet rs){
                String result = null;
                try {
                    while(rs.next()){
                        result =  rs.getString("algorithm_schedule");
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                return result;
            }
        });
    }
    
    public String getAlgorithmProcessBySubTaskHash(String subtaskhash) {
        String sql = "select algorithm_schedule from `socket_log` where task_hash = ?";
        Object[] params = {subtaskhash};
        return (String) Query.executeQueryObject(sql, params, new QueryCallBack() {
            @Override
            public Object doExecute(ResultSet rs){
                String result = null;
                try {
                    while(rs.next()){
                        result =  rs.getString("algorithm_schedule");
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                return result;
            }
        });
    }
}
